package com.shortlink.admin.controller;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shortlink.admin.dao.entity.GroupDO;
import com.shortlink.admin.dao.entity.ShortLinkDO;
import com.shortlink.admin.dto.req.shortlinkstats.GroupShortLinkStatsReqDTO;
import com.shortlink.admin.remote.ShortLinkStatsRemoteService;
import com.shortlink.admin.remote.dto.shortlinkmapper.ShortLinkReqDTO;
import com.shortlink.admin.remote.dto.shortlinkstats.BatchShortLinkStatsReqDTO;
import com.shortlink.admin.remote.dto.shortlinkstats.ShortLinkStatsRecordVO;
import com.shortlink.admin.remote.dto.shortlinkstats.ShortLinkStatsVO;
import com.shortlink.admin.remote.dto.shortlinkstats.SignalShortLinkStatsReqDTO;
import com.shortlink.admin.service.GroupService;
import com.shortlink.admin.service.ShortLinkService;
import com.shortlink.common.base.BasePageReqDTO;
import com.shortlink.common.base.Result;
import com.shortlink.common.exception.ClientException;
import com.shortlink.common.user.UserContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;
import java.util.List;

/**
 * 短链接监控控制层
 *
 * @author wp
 */
@Slf4j
@RestController
@RequiredArgsConstructor
public class ShortLinkStatsAdminController {
    private final ShortLinkStatsRemoteService shortLinkStatsRemoteService;
    private final ShortLinkService shortLinkService;
    private final GroupService groupService;

    /**
     * 访问单个短链接指定时间内监控数据
     */
    @GetMapping("/web-api/stats/shortlink/info")
    public Result<ShortLinkStatsVO> signalShortLinkStats(SignalShortLinkStatsReqDTO signalShortLinkStats) {
        verifySignalShortLinkParam(signalShortLinkStats);
        return shortLinkStatsRemoteService.signalShortLinkStats(signalShortLinkStats);
    }

    /**
     * 访问分组短链接指定时间内监控数据
     */
    @GetMapping("/web-api/stats/group/info")
    public Result<ShortLinkStatsVO> groupShortLinkStats(GroupShortLinkStatsReqDTO groupShortLinkStats) {
        LocalDate startDate = groupShortLinkStats.getStartDate();
        LocalDate endDate = groupShortLinkStats.getEndDate();
        verifyGroupShortLinkParam(groupShortLinkStats);

        List<ShortLinkReqDTO> shortLinks = shortLinkService.queryShortLinkByGid(groupShortLinkStats.getGid());

        BatchShortLinkStatsReqDTO batchShortLinkStats = new BatchShortLinkStatsReqDTO(shortLinks, startDate, endDate);
        return shortLinkStatsRemoteService.batchShortLinkStats(batchShortLinkStats);
    }

    /**
     * 访问单个短链接指定时间内访问记录监控数据
     */
    @GetMapping("/web-api/stats/shortlink/record")
    public Result<Page<ShortLinkStatsRecordVO>> signalShortLinkStatsRecord(SignalShortLinkStatsReqDTO signalShortLinkStats,
                                                                           BasePageReqDTO page) {
        verifySignalShortLinkParam(signalShortLinkStats);
        return shortLinkStatsRemoteService.signalShortLinkStatsRecord(signalShortLinkStats, page);
    }

    /**
     * 访问分组短链接指定时间内访问记录监控数据
     */
    @GetMapping("/web-api/stats/group/record")
    public Result<Page<ShortLinkStatsRecordVO>> groupShortLinkStatsRecord(GroupShortLinkStatsReqDTO groupShortLinkStats,
                                                                          BasePageReqDTO page) {
        LocalDate startDate = groupShortLinkStats.getStartDate();
        LocalDate endDate = groupShortLinkStats.getEndDate();
        verifyGroupShortLinkParam(groupShortLinkStats);

        List<ShortLinkReqDTO> shortLinks = shortLinkService.queryShortLinkByGid(groupShortLinkStats.getGid());

        BatchShortLinkStatsReqDTO batchShortLinkStats = new BatchShortLinkStatsReqDTO(shortLinks, startDate, endDate);
        return shortLinkStatsRemoteService.batchShortLinkStatsRecord(batchShortLinkStats, page);
    }

    private void verifySignalShortLinkParam(SignalShortLinkStatsReqDTO signalShortLinkStats) {
        String shortUri = signalShortLinkStats.getShortUri();
        LocalDate startDate = signalShortLinkStats.getStartDate();
        LocalDate endDate = signalShortLinkStats.getEndDate();
        if (!ObjectUtil.isAllNotEmpty(shortUri)) {
            log.info(String.format("shortUri(%s) 不能为空", shortUri));
            throw new ClientException("参数错误");
        }
        validDate(startDate, endDate);

        boolean exists = shortLinkService.lambdaQuery()
                .eq(ShortLinkDO::getShortUri, shortUri)
                .eq(ShortLinkDO::getUserId, UserContext.getUserId())
                .eq(ShortLinkDO::getDelFlag, ShortLinkDO.DEL_FLAG_FAIL)
                .exists();
        if (!exists) {
            log.info("用户短链接不存在");
            throw new ClientException("参数错误");
        }
    }

    private void verifyGroupShortLinkParam(GroupShortLinkStatsReqDTO groupShortLinkStats) {
        Long gid = groupShortLinkStats.getGid();
        LocalDate startDate = groupShortLinkStats.getStartDate();
        LocalDate endDate = groupShortLinkStats.getEndDate();
        if (!ObjectUtil.isAllNotEmpty(gid)) {
            log.info(String.format("gid(%s) 不能为空", gid));
            throw new ClientException("参数错误");
        }
        validDate(startDate, endDate);

        boolean exists = groupService.lambdaQuery()
                .eq(GroupDO::getId, gid)
                .eq(GroupDO::getUserId, UserContext.getUserId())
                .eq(GroupDO::getDelFlag, GroupDO.DEL_FLAG_FAIL)
                .exists();
        if (!exists) {
            log.info("用户分组不存在");
            throw new ClientException("参数错误");
        }
    }

    private void validDate(LocalDate startDate, LocalDate endDate) {
        if (!ObjectUtil.isAllNotEmpty(startDate, endDate)) {
            log.info(String.format("startDate(%s) endDate(%s) 不能为空", startDate, endDate));
            throw new ClientException("参数错误");
        }
        if (!startDate.isBefore(endDate)) {
            log.info(String.format("startDate(%s) endDate(%s) 开始时间大于结束时间", startDate, endDate));
            throw new ClientException("参数错误");
        }
    }
}
